package com.mi.million.module.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.mi.million.common.util.CacheKey;
import com.mi.million.module.system.service.RoleService;
import com.mi.million.mybatis.entity.*;
import com.mi.rule.cache.CacheKit;
import com.mi.rule.db.core.MiPage;
import com.mi.rule.db.core.MiWrapper;
import com.mi.rule.db.dao.MiDao;
import com.mi.rule.util.project.SRS;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 资源表 服务实现类
 * </p>
 *
 * @author 王永吉
 */
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    private MiDao dao;

    //角色列表
    @Override
    public List<SysRole> roles() {
        String s = CacheKit.instance().get(CacheKey.key_role_list);
        if (s == null) {
            List<SysRole> list = dao.list(SysRole.class);
            CacheKit.instance().set(CacheKey.key_role_list, JSON.toJSONString(list));
            return list;
        }
        return JSON.parseArray(s, SysRole.class);
    }

    //修改角色资源
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SRS updateRoleResource(SRS param) {
        String roleId = param.getString("roleId");
        JSONArray resourceIds = param.getJSONArray("resourceIds");

        //修改角色资源关联表
        //删除
        dao.delete(new MiWrapper<>(SysLinkRoleResource.class).eq(SysLinkRoleResource.ROLE_ID, roleId));

        //重新插入
        ArrayList<SysLinkRoleResource> objects = new ArrayList<>();
        for (Object resourceId : resourceIds) {
            SysLinkRoleResource sysLinkRoleResource = new SysLinkRoleResource();
            sysLinkRoleResource.setRoleId(roleId);
            sysLinkRoleResource.setResourceId(resourceId.toString());
            objects.add(sysLinkRoleResource);
        }
        dao.insertBatch(objects);

        //刷新缓存

        CacheKit.instance().delete(CacheKey.key_role_resource_url + roleId);
        CacheKit.instance().delete(CacheKey.key_role_resource_list + roleId);

        return SRS.bySuccess();
    }

    //修改角色菜单
    @Override
    public SRS updateRoleMenu(SRS param) {
        String roleId = param.getString("roleId");
        JSONArray menuIds = param.getJSONArray("menuIds");

        //修改角色菜单关联表
        //删除
        dao.delete(new MiWrapper<>(SysLinkRoleMenu.class).eq(SysLinkRoleMenu.ROLE_ID, roleId));
        //重新插入
        ArrayList<SysLinkRoleMenu> objects = new ArrayList<>();
        for (Object menuId : menuIds) {
            SysLinkRoleMenu linkRoleMenu = new SysLinkRoleMenu();
            linkRoleMenu.setRoleId(roleId);
            linkRoleMenu.setMenuId(menuId.toString());
            objects.add(linkRoleMenu);
        }
        dao.insertBatch(objects);

        //删除缓存
        deleteRoleMenuCache(roleId);
        return SRS.bySuccess();
    }

    @Override
    public SRS insertSysRole(SysRole role) {
        dao.insert(role);
        //删除角色缓存
        CacheKit.instance().delete(CacheKey.key_role_list);
        return SRS.bySuccess();
    }

    @Override
    public SRS deleteSysRole(Object[] ids) {
        dao.deleteByIds(SysRole.class, Arrays.asList(ids));
        //删除角色相关缓存
        CacheKit.instance().delete(CacheKey.key_role_list);
        for (Object roleId : ids) {
            deleteRoleMenuCache(roleId);
            deleteRoleResourceCache(roleId);
        }
        return SRS.bySuccess();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SRS updateSysRole(SRS param) {
        //修改角色信息
        SysRole sysRole = new SysRole();
        sysRole.setId(param.getString("id"));
        sysRole.setCode(param.getString("code"));
        sysRole.setName(param.getString("name"));
        dao.update(sysRole);

        //修改角色菜单
        MiWrapper<SysLinkRoleMenu> wrapper1 = new MiWrapper<>(SysLinkRoleMenu.class);
        wrapper1.eq(SysLinkRoleMenu.ROLE_ID, sysRole.getId());
        dao.delete(wrapper1);
        ArrayList<SysLinkRoleMenu> linkRoleMenus = new ArrayList<>();
        for (Object menuId : param.getJSONArray("menuCheckIds")) {
            SysLinkRoleMenu linkRoleMenu = new SysLinkRoleMenu();
            linkRoleMenu.setRoleId(sysRole.getId());
            linkRoleMenu.setMenuId(menuId + "");
            linkRoleMenus.add(linkRoleMenu);
        }
        dao.insertBatch(linkRoleMenus);

        //修改角色资源
        MiWrapper<SysLinkRoleResource> wrapper2 = new MiWrapper<>(SysLinkRoleResource.class);
        wrapper2.eq(SysLinkRoleResource.ROLE_ID, sysRole.getId());
        dao.delete(wrapper2);
        ArrayList<SysLinkRoleResource> linkRoleResources = new ArrayList<>();
        for (Object resourceId : param.getJSONArray("resourceCheckIds")) {
            SysLinkRoleResource linkRoleResource = new SysLinkRoleResource();
            linkRoleResource.setRoleId(sysRole.getId());
            linkRoleResource.setResourceId(resourceId + "");
            linkRoleResources.add(linkRoleResource);
        }
        dao.insertBatch(linkRoleResources);
        //删除缓存
        CacheKit.instance().delete(CacheKey.key_role_list);
        deleteRoleMenuCache(sysRole.getId());
        deleteRoleResourceCache(sysRole.getId());
        return SRS.bySuccess();
    }

    @Override
    public SRS pageSysRole(SRS param) {
        MiWrapper<SysRole> wrapper = new MiWrapper<>(SysRole.class);
        wrapper.eq("1", 1);
        wrapper.like(notBlank(param.get("id")), SysRole.ID, param.get("id"));
        wrapper.like(notBlank(param.get("name")), SysRole.NAME, param.get("name"));
        wrapper.like(notBlank(param.get("code")), SysRole.CODE, param.get("code"));
        MiPage<SysRole> page = dao.page(new MiPage<>(param), wrapper);
        return SRS.bySuccess(page);
    }

    @Override
    public SRS listSysRole(SRS param) {
        MiWrapper<SysRole> wrapper = new MiWrapper<>(SysRole.class);
        wrapper.eq("1", 1);

        wrapper.like(notBlank(param.get("id")), SysRole.ID, param.get("id"));
        List<SysRole> list = dao.list(wrapper);
        return SRS.bySuccess(list);
    }

    @Override
    public SRS infoSysRole(SRS param) {
        SysRole dict = dao.selectById(SysRole.class, param.getString("id"));
        return SRS.bySuccess(dict);
    }

    //清除角色菜单缓存
    private void deleteRoleMenuCache(Object roleId) {
        CacheKit.instance().delete(CacheKey.key_role_menu_url + roleId);
        CacheKit.instance().delete(CacheKey.key_role_menu_id + roleId);
        CacheKit.instance().delete(CacheKey.key_role_menu_list + roleId);
    }

    //删除角色资源缓存
    private void deleteRoleResourceCache(Object roleId) {
        CacheKit.instance().delete(CacheKey.key_role_resource_url + roleId);
        CacheKit.instance().delete(CacheKey.key_role_resource_id + roleId);
        CacheKit.instance().delete(CacheKey.key_role_resource_list + roleId);
    }

    //角色菜单Urls
    @Override
    public List<String> roleMenuUrls(Object roleId) {
        String s = CacheKit.instance().get(CacheKey.key_role_menu_url + roleId);
        if (s == null) {
            List<String> menuIds = dao.listObj(
                    new MiWrapper<>(SysLinkRoleMenu.class)
                            .select(SysLinkRoleMenu.MENU_ID)
                            .eq(SysLinkRoleMenu.ROLE_ID, roleId),
                    String.class);
            List<SysMenu> sysMenus = dao.listByIds(SysMenu.class, menuIds);
            List<String> urls = sysMenus.stream().map(SysMenu::getPath).collect(Collectors.toList());
            CacheKit.instance().set(CacheKey.key_role_menu_url + roleId, JSON.toJSONString(urls));
            return urls;
        }

        return JSON.parseArray(s, String.class);
    }

    //角色菜单Ids
    @Override
    public List<String> roleMenuIds(String roleId) {
        String s = CacheKit.instance().get(CacheKey.key_role_menu_id + roleId);
        if (s == null) {
            List<String> menuIds = dao.listObj(
                    new MiWrapper<>(SysLinkRoleMenu.class)
                            .select(SysLinkRoleMenu.MENU_ID)
                            .eq(SysLinkRoleMenu.ROLE_ID, roleId),
                    String.class);
            List<SysMenu> sysMenus = dao.listByIds(SysMenu.class, menuIds);
            List<String> ids = sysMenus.stream().map(SysMenu::getId).collect(Collectors.toList());
            CacheKit.instance().set(CacheKey.key_role_menu_id + roleId, JSON.toJSONString(ids));
            return ids;
        }
        return JSON.parseArray(s, String.class);

    }

    //角色菜单List
    @Override
    public List<SysMenu> roleMenuList(String roleId) {
        String s = CacheKit.instance().get(CacheKey.key_role_menu_list + roleId);
        if (s == null) {
            List<String> menuIds = dao.listObj(new MiWrapper<>(SysLinkRoleMenu.class).select(SysLinkRoleMenu.MENU_ID).eq(SysLinkRoleMenu.ROLE_ID, roleId), String.class);
            List<SysMenu> sysMenus = dao.listByIds(SysMenu.class, menuIds);
            CacheKit.instance().set(CacheKey.key_role_menu_list + roleId, JSON.toJSONString(sysMenus));
            return sysMenus;
        }
        return JSON.parseArray(s, SysMenu.class);

    }

    //角色菜单List(不包含PID=0)
    @Override
    public List<SysMenu> roleMenuList(List roleIds) {
        HashSet<SysMenu> hashSet = new HashSet<>();
        for (Object roleId : roleIds) {
            List<SysMenu> menuList = roleMenuList(roleId + "");
            hashSet.addAll(menuList);
        }
        return new ArrayList<>(hashSet);
    }

    //角色资源Urls
    @Override
    public List<String> roleResourceUrls(Object roleId) {
        String s = CacheKit.instance().get(CacheKey.key_role_resource_url + roleId);
        if (s == null) {
            List<String> resourceIds = dao.listObj(new MiWrapper<>(SysLinkRoleResource.class).select(SysLinkRoleResource.RESOURCE_ID).eq(SysLinkRoleResource.ROLE_ID, roleId), String.class);
            List<SysResource> sysMenus = dao.listByIds(SysResource.class, resourceIds);
            List<String> urls = sysMenus.stream().map(SysResource::getUrl).collect(Collectors.toList());
            CacheKit.instance().set(CacheKey.key_role_resource_url + roleId, JSON.toJSONString(urls));
            return urls;
        }
        return JSON.parseArray(s, String.class);

    }

    //角色资源Ids
    @Override
    public List<String> roleResourceIds(String roleId) {
        String s = CacheKit.instance().get(CacheKey.key_role_resource_id + roleId);
        if (s == null) {
            List<String> resourceIds = dao.listObj(new MiWrapper<>(SysLinkRoleResource.class).select(SysLinkRoleResource.RESOURCE_ID).eq(SysLinkRoleResource.ROLE_ID, roleId), String.class);
            List<SysResource> sysMenus = dao.listByIds(SysResource.class, resourceIds);
            List<String> ids = sysMenus.stream().map(SysResource::getId).collect(Collectors.toList());
            CacheKit.instance().set(CacheKey.key_role_resource_id + roleId, JSON.toJSONString(ids));
            return ids;
        }
        return JSON.parseArray(s, String.class);

    }

    //角色资源Urls
    @Override
    public List<String> roleResourceUrls2(List<?> roleIds) {
        HashSet<String> hashSet = new HashSet<>();
        for (Object roleId : roleIds) {
            List<String> strings = roleResourceUrls(roleId);
            hashSet.addAll(strings);
        }
        return new ArrayList<>(hashSet);
    }

    //角色资源List
    @Override
    public List<SysResource> roleResourceList(String roleId) {
        String s = CacheKit.instance().get(CacheKey.key_role_resource_list + roleId);
        if (s == null) {
            List<String> resourceIds = dao.listObj(new MiWrapper<>(SysLinkRoleResource.class).select(SysLinkRoleResource.RESOURCE_ID).eq(SysLinkRoleResource.ROLE_ID, roleId), String.class);
            List<SysResource> sysMenus = dao.listByIds(SysResource.class, resourceIds);
            CacheKit.instance().set(CacheKey.key_role_resource_list + roleId, JSON.toJSONString(sysMenus));
            return sysMenus;
        }
        return JSON.parseArray(s, SysResource.class);

    }

    //角色资源Ids
    @Override
    public List<SysResource> roleResourceList(List roleIds) {
        HashSet<SysResource> hashSet = new HashSet<>();
        for (Object roleId : roleIds) {
            hashSet.addAll(roleResourceList(roleId + ""));
        }
        return new ArrayList<>(hashSet);
    }

}